package atack.tesis.kelluntekun.ui.componentes;

import java.io.Serializable;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

import org.vaadin.aceeditor.gwt.ace.AceMode;


import atack.tesis.kelluntekun.KelluntekunApplication;
import atack.tesis.kelluntekun.domain.Etiqueta;
import atack.tesis.kelluntekun.domain.Snippet;
import atack.tesis.kelluntekun.ui.componentes.utils.UiUtils;

import com.vaadin.addon.jpacontainer.JPAContainer;
import com.vaadin.addon.jpacontainer.JPAContainerFactory;
import com.vaadin.addon.jpacontainer.util.DefaultQueryModifierDelegate;
import com.vaadin.data.Container;
import com.vaadin.data.Container.Filter;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.util.filter.Compare;
import com.vaadin.data.util.filter.Like;
import com.vaadin.terminal.Sizeable;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.Table;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.VerticalSplitPanel;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.themes.Reindeer;

public class SearchResultWindow extends Window implements Serializable{
	private static final long serialVersionUID = 1L;
	
	private VerticalLayout vlyMain;
	private VerticalSplitPanel vertSplit;
	private HorizontalSplitPanel hrzlSplit;
	private HorizontalLayout hlyBusquedaAvanzada;
	private TabSheet t;
	private VerticalLayout vlySnippetsTable;
	private codeInfoView civ;
	
	private JPAContainer<Snippet> snippetsSearch;
	
	private TextField tfTitulo;
	private TextField tfDescripcion;
	private TextField tfEtiqueta;
	private ComboBox cbLenguaje;
	private Table tSnippets;
	private Button btSearch;
	
	public SearchResultWindow(){
		
		buildMain();
		buildHlyBusquedaAvanzada();
		buildVlyMain();
		
		vertSplit.addComponent(hlyBusquedaAvanzada);
		vertSplit.addComponent(vlyMain);
		
		this.setContent(vertSplit);
	}
	
	public SearchResultWindow(Container searchResults){
		this.snippetsSearch = (JPAContainer<Snippet>) searchResults;
		
		buildMain();
		buildHlyBusquedaAvanzada();
		buildVlyMain();
		//TODO 
//		tSnippets= new Table(null,this.snippetsSearch);
		buildTableCodes();
		tSnippets.setContainerDataSource(this.snippetsSearch);
		tSnippets.setVisibleColumns(new String[]{"titulo","usuario"});
//		tSnippets.setColumnHeader("titulo", "Snippets");
		tSnippets.addListener(gettSnippetsListener());
		vlySnippetsTable.addComponent(tSnippets);
		
		vertSplit.addComponent(hlyBusquedaAvanzada);
		vertSplit.addComponent(vlyMain);
		
		this.setContent(vertSplit);
	}
	
	/**
	 * Construye las estructura base de la ventana de búsqueda.
	 * (la ventana propiamente tal, el verticalSplit panel que divide los campos de búsqueda de los resultados.)
	 */
	private void buildMain(){
		this.setModal(true);
		this.setHeight("97%");
		this.setWidth("85%");
		this.setCaption("Búsquedas");
		this.setResizable(false);
		
		vertSplit = new VerticalSplitPanel();
		vertSplit.setHeight("100%");
		vertSplit.setWidth("100%");
		vertSplit.setSplitPosition(60, Sizeable.UNITS_PIXELS);
		vertSplit.setLocked(true);
		vertSplit.setStyleName(Reindeer.SPLITPANEL_SMALL);
		
//		vlyMain.addComponent(UiUtils.getLbSpace("200px", "3px"));
	}
	
	private void buildHlyBusquedaAvanzada(){
		hlyBusquedaAvanzada = new HorizontalLayout();
		hlyBusquedaAvanzada.setWidth("665px");
		hlyBusquedaAvanzada.setHeight(null);
		hlyBusquedaAvanzada.setSpacing(true);
		hlyBusquedaAvanzada.setMargin(false, false, true, true);
//		hlySearch.setStyleName(Reindeer.LAYOUT_WHITE);
		
		tfTitulo = new TextField("Título: ");
		tfTitulo.setWidth("150px");
		tfTitulo.setImmediate(true);
		tfTitulo.setNullRepresentation("");
//		tfSearch.setStyleName(Reindeer.LAYOUT_WHITE);
		hlyBusquedaAvanzada.addComponent(tfTitulo);
		
		tfDescripcion = new TextField("Descripción: ");
		tfDescripcion.setWidth("230px");
		tfDescripcion.setImmediate(true);
		tfDescripcion.setNullRepresentation("");
		hlyBusquedaAvanzada.addComponent(tfDescripcion);
		
		tfEtiqueta = new TextField("Etiqueta: ");
		tfEtiqueta.setWidth("100px");
		tfEtiqueta.setImmediate(true);
		tfEtiqueta.setNullRepresentation("");
		hlyBusquedaAvanzada.addComponent(tfEtiqueta);
		
		cbLenguaje = new ComboBox("Lenguaje: ");
		cbLenguaje.setNullSelectionAllowed(true);
		cbLenguaje.setInputPrompt("Selecciona...");
		for(AceMode mode:AceMode.values()){
			cbLenguaje.addItem(mode);
		}
		cbLenguaje.setImmediate(true);
		cbLenguaje.setRequired(false);
		cbLenguaje.setWidth("90px");
		hlyBusquedaAvanzada.addComponent(cbLenguaje);
		
		btSearch = new Button(">");
		btSearch.setWidth(null);
		btSearch.setStyleName(Reindeer.BUTTON_DEFAULT);
		btSearch.addListener(getBtSearchListener());
		hlyBusquedaAvanzada.addComponent(btSearch);
		hlyBusquedaAvanzada.setComponentAlignment(btSearch, Alignment.BOTTOM_RIGHT);
		
	}

	/**
	 * construye el layaout con la tabla de snippets y la info de cada snippet.
	 */
	private void buildVlyMain(){
		vlyMain = new VerticalLayout();
		vlyMain.setSizeFull();
		vlyMain.setSpacing(false);
		vlyMain.setMargin(false);
		
		t = new TabSheet();
		t.setStyleName(Reindeer.TABSHEET_SMALL);
		t.setSizeFull();
		vlyMain.addComponent(t);
		
		hrzlSplit = new HorizontalSplitPanel();
		hrzlSplit.setHeight("100%");
		hrzlSplit.setWidth("100%");
		hrzlSplit.setSplitPosition(20,Sizeable.UNITS_PERCENTAGE);
		hrzlSplit.setStyleName(Reindeer.SPLITPANEL_SMALL);
		t.addTab(hrzlSplit, "Resultados");
		
		vlySnippetsTable = new VerticalLayout();
		vlySnippetsTable.setMargin(false);
		vlySnippetsTable.setSpacing(false);
		hrzlSplit.addComponent(vlySnippetsTable);
	}
	
	/**
	 * crea el listener para ver el detealle de cada snippet como resultado de un búsqueda.
	 * @return Listener.
	 */
	private Table.ValueChangeListener gettSnippetsListener(){
		return (new Table.ValueChangeListener(){
			private static final long serialVersionUID = 1L;
			
			public void valueChange(ValueChangeEvent event){
				if(event.getProperty().getValue()!=null){
					Snippet selectedSnippet = snippetsSearch.getItem((Long) event.getProperty().getValue()).getEntity();
					civ = new codeInfoView();
					//TODO cargar etiquetas correctamente.
					civ.setSnippet(selectedSnippet);
					civ.removeButtons();
					hrzlSplit.setSecondComponent(civ);
//					addCodeInfoViewListeners();
//					ct.setRightComponent(civ);
				}
				else{
//					idSelectedSnippet= Long.parseLong("0");
				}
            }
        });
	}

	private Button.ClickListener getBtSearchListener(){
		return(new Button.ClickListener(){
			private static final long serialVersionUID = 1L;
			public void buttonClick(ClickEvent event){
				
				buildSnippetsSearchContainer();
				buildFilters();
				
				if (!snippetsSearch.getFilters().isEmpty()&&snippetsSearch.size()>=1){
					if (vlySnippetsTable.getComponentIndex(tSnippets)!=-1) {
						vlySnippetsTable.removeComponent(tSnippets);
					}
					buildTableCodes();
					tSnippets.setContainerDataSource(snippetsSearch);
					tSnippets.setVisibleColumns(new String[]{"titulo","usuario"});
//					tSnippets.setColumnHeader("titulo", "Snippets");
					tSnippets.addListener(gettSnippetsListener());
					vlySnippetsTable.addComponent(tSnippets);
					removeCodeInfoView();
					resetFields();
				}
				else{
					if (vlySnippetsTable.getComponentIndex(tSnippets)!=-1) {
						vlySnippetsTable.removeComponent(tSnippets);
					}
					removeCodeInfoView();
					getWindow().showNotification(UiUtils.getWarningNotification("<center>Tu Búsqueda no arroja resultados</center>", ""));
				}
				
			}
		});
	}
	
//	public busquedaAvanzadaIsValid(){
////		if()
//	}

	/**
	 * @return the tSnippets
	 */
	public Table gettSnippets() {
		return tSnippets;
	}

	/**
	 * @param tSnippets the tSnippets to set
	 */
	public void settSnippets(Table tSnippets) {
		this.tSnippets = tSnippets;
	}

	/**
	 * @return the vlyMain
	 */
	public VerticalLayout getVlyMain() {
		return vlyMain;
	}
	
	/**
	 * Construye el JPAContainer para la busqueda de Snippets.
	 */
	private void buildSnippetsSearchContainer(){
		snippetsSearch = JPAContainerFactory.make(Snippet.class,KelluntekunApplication.PERSISTENCE_UNIT);
		snippetsSearch.removeAllContainerFilters();
		snippetsSearch.setReadOnly(true);
		snippetsSearch.setQueryModifierDelegate(new DefaultQueryModifierDelegate(){
			private static final long serialVersionUID = 1L;
			@Override
            public void queryWillBeBuilt(CriteriaBuilder criteriaBuilder, CriteriaQuery<?> query){
                query.distinct(true);
            }
        });
	}
	
	/**
	 * Verifica si una etiqueta en particular exsite en la BD si es así la retorna.
	 * @param tag
	 * @return la entidad etiqueta o nulo si no está.
	 */
	private Etiqueta getEtiquetaFromBD(String tag){
		JPAContainer<Etiqueta> tempTags =  JPAContainerFactory.make(Etiqueta.class, KelluntekunApplication.PERSISTENCE_UNIT);
		Filter filtroTags= new Compare.Equal("etiqueta",tag);
		tempTags.addContainerFilter(filtroTags);
		
		if (tempTags.size()>=1){
			return tempTags.getItem(tempTags.firstItemId()).getEntity();
		}
		else{
			return null;
		}
	}
	
	/**
	 * Rescata los valores de los campos de texto y va agregando los filtros para la búsqueda avanzada según corresponda.
	 */
	private void buildFilters(){
		
		if(!tfTitulo.getValue().toString().equals("")){
			Filter fLikeTitulo = new Like("titulo", "%"+tfTitulo.getValue().toString()+"%", false);
			snippetsSearch.addContainerFilter(fLikeTitulo);
		}
		if (!tfDescripcion.getValue().toString().equals("")){
			Filter fLikeDescripcion = new Like("descripcion", "%"+tfDescripcion.getValue().toString()+"%", false);
			snippetsSearch.addContainerFilter(fLikeDescripcion);
		}
		if(!tfEtiqueta.getValue().toString().equals("")){
			//SEARCH ETIQUETAS
			Etiqueta temp = getEtiquetaFromBD(tfEtiqueta.getValue().toString());
			if(temp!=null){
				Filter ftags = new Compare.Equal("etiquetas",temp);
				snippetsSearch.addContainerFilter(ftags);
			}
		}
		if (cbLenguaje.getValue()!=null){
			AceMode leng = (AceMode) cbLenguaje.getValue();
			Filter fLenguaje = new Compare.Equal("lenguaje", leng);
			snippetsSearch.addContainerFilter(fLenguaje);
		}
		
	}
	
	/**
	 * Construye con "desfase" la tabla en la que se muestran los codigos
	 * 
	 */
	public void buildTableCodes(){
		
		tSnippets= new Table();
		tSnippets.setWidth("100%");
		tSnippets.setSelectable(true);
		tSnippets.setMultiSelect(false);
		tSnippets.setNullSelectionAllowed(true);
		tSnippets.setImmediate(true);
		tSnippets.setPageLength(0);
		tSnippets.setStyleName(Reindeer.TABLE_STRONG);
//		vlySnippetsTable.addComponent(tCodes);
	}
	
	/**
	 * Remueve el componente a la derecha del hrSplit.
	 * para el caso será 'codeInfoWiew'
	 */
	private void removeCodeInfoView(){
		if(this.hrzlSplit.getSecondComponent()!=null){
			this.hrzlSplit.removeComponent(this.hrzlSplit.getSecondComponent());
		}
	}
	
	private void resetFields(){
		this.tfTitulo.setValue("");
		this.tfDescripcion.setValue("");
		this.tfEtiqueta.setValue("");
		this.cbLenguaje.setValue(null);
	}
	

}
